package com.shockweb.service.init.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.shockweb.common.utils.FileTools;
import com.shockweb.service.ServiceServer;
import com.shockweb.service.ServiceServerException;
import com.shockweb.service.config.ServiceConfig;
import com.shockweb.service.data.ServiceStatus;
import com.shockweb.service.init.Initialization;
import com.shockweb.service.ioc.IocManager;
import com.shockweb.service.ioc.defaultconfig.Service;
import com.shockweb.service.ioc.impl.DefaultIocInvokeImpl;

/**
 * 默认初始化类
 * 
 * @author 彭明华
 * 2018年1月19日 创建
 */
public class DefaultInitImpl implements Initialization{

	
	/**
	 * 初始化方法
	 */
	public void init(String path,ServiceConfig config)throws ServiceServerException{
		try{
			
    		if(path.startsWith("classpath:")){
    			ClassLoader classLoader = null;
    			if(Thread.currentThread()!=null){
    				classLoader = Thread.currentThread().getContextClassLoader();
    			}else{
    				classLoader = ServiceServer.class.getClassLoader();
    			}
    			path = classLoader.getResource(path.substring("class:".length())).getPath();
    		}
	    	String file = null;
	    	if(new File(path).isFile()){
	    		file = path;
	    	}else if(new File(path).isDirectory()){
	    		file = FileTools.getFullPathFileName(path,"default.xml");
	    	}else{
	    		throw new ServiceServerException("配置文件路径" + path + "非法");
	    	}
			Map<String,Service> beans = xmlreader(file);
			putServiceStatus(beans);
			IocManager.add(new DefaultIocInvokeImpl(beans));
		}catch(ServiceServerException e){
			throw e;
		}catch(Exception e){
			throw new ServiceServerException("读取配置文件出错");
		}
	}
	
	/**
	 * 发布所有服务
	 */
	public static void putServiceStatus(Map<String,Service> beans)throws ServiceServerException{
		if(beans!=null){
			Iterator<Entry<String,Service>> its = beans.entrySet().iterator();
			while(its.hasNext()){
				Entry<String,Service> entry = its.next();
				if(ServiceStatus.getServices().getServiceDefines().containsKey(entry.getKey())){
					throw new ServiceServerException("注册'" + entry.getKey() + "'服务名定义重复");
				}else{
					ServiceStatus.getServices().add(entry.getKey());
				}
			}
		}
	}


	/**
	 * 解析xml定义nodeList对象
	 * 
	 * @author 彭明华
	 * 2018年1月18日 创建
	 */
    class NodeLists implements NodeList{
    	/**
    	 * 所有的节点
    	 */
        protected Vector<Node> nodes = new Vector<Node>();
        
        /**
         * 添加dom节点
         * @param node
         */
        public void add(Node node){
        	nodes.add(node);
        }
        
        /**
         * 获取一个节点
         */
		public Node item(int index) {
			return nodes.get(index);
		}

		/**
		 * 节点的数量
		 */
		public int getLength() {
			return nodes.size();
		}
    	
    }
    
    /**
     * 获取name对应的NodeList
     * @param element
     * @param name
     * @return
     */
    public NodeList getElementsCurrByTagName(Element element,String name){
    	NodeLists lists = new NodeLists();
    	NodeList nodes = element.getChildNodes();
    	for(int i=0;i<nodes.getLength();i++){
    		if(nodes.item(i).getNodeName().equals(name)){
    			lists.add(nodes.item(i));
    		}
    	}
    	return lists;
    }
    
    /**
     * 读取xml文件
     * @param iocConfig
     * @return
     * @throws ServiceServerException
     * @throws SAXException
     * @throws IOException
     * @throws ParserConfigurationException
     */
	private Map<String,Service> xmlreader(String iocConfig) throws ServiceServerException,SAXException, IOException, ParserConfigurationException{
		FileInputStream f = null;
		try{
			if(new File(iocConfig).exists()){
				f = new FileInputStream(iocConfig);
			}else{
				f = new FileInputStream(FileTools.getFullPathFileName(FileTools.getClassPath(), iocConfig));
			}
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			Element element = dbf.newDocumentBuilder().parse(f).getDocumentElement();
			Map<String,Service> allServices = new HashMap<String,Service>();
			
        	NodeList nodes = getElementsCurrByTagName(element,"bean");
        	for(int i=0;i<nodes.getLength();i++){
        		Element e = (Element)nodes.item(i);
      			Service service = new Service();
      			if(e.getAttribute("class")!=null && !e.getAttribute("class").trim().equals("")){
      				service.setClass(e.getAttribute("class"));
      			}
    			if(e.getAttribute("scope")!=null && !e.getAttribute("scope").trim().equals("")){
    				service.setScope(e.getAttribute("scope"));
    			}
    			if(e.getAttribute("before")!=null && !e.getAttribute("before").trim().equals("")){
    				service.setBefore(e.getAttribute("before"));
    			}
    			if(e.getAttribute("returning")!=null && !e.getAttribute("returning").trim().equals("")){
    				service.setReturning(e.getAttribute("returning"));
    			}
    			if(e.getAttribute("throwing")!=null && !e.getAttribute("throwing").trim().equals("")){
    				service.setThrowing(e.getAttribute("throwing"));
    			}
    			String name = null;
    			if(e.getAttribute("name")!=null && !e.getAttribute("name").trim().equals("")){
    				name = e.getAttribute("name");
    			}
    			if(allServices.containsKey(name)){
    				throw new ServiceServerException("'" + name + "'服务名定义重复");
    			}
        		allServices.put(name, service);
        	}
			return allServices;
        }finally{
        	if(f!=null){
        		try {
					f.close();
				} catch (IOException e) {
				}
        	}
        }
	}

}
